/**
 * 
 */
package com.attilax.dataspider;

/**
 * @author attilax
 *2016年9月27日 下午6:41:16
 */

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.commons.httpclient.params.HttpConnectionParams;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.params.ConnManagerParams;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.HttpParams;

import com.attilax.exception.ExUtil;
import com.attilax.io.StreamUtil;
import com.attilax.io.filex;
import com.attilax.net.GetDataByURL;

public class HttpDownloader {
	// SSL handler (ignore untrusted hosts)
	private static TrustManager truseAllManager = new X509TrustManager() {
		@Override
		public X509Certificate[] getAcceptedIssuers() {
			return null;
		}

		@Override
		public void checkServerTrusted(X509Certificate[] chain, String authType)
				throws CertificateException {
		}

		@Override
		public void checkClientTrusted(X509Certificate[] chain, String authType)
				throws CertificateException {
		}
	};

	private static void enableSSL(HttpClient httpClient) {
		try {
			SSLContext sslcontext = SSLContext.getInstance("TLS");
			sslcontext.init(null, new TrustManager[] { truseAllManager }, null);
			SSLSocketFactory sf = new SSLSocketFactory(sslcontext);
			sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
			Scheme https = new Scheme("https", sf, 443);
			httpClient.getConnectionManager().getSchemeRegistry()
					.register(https);
		} catch (KeyManagementException e) {
			e.printStackTrace();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) throws Exception {

		// String url = "https://mail.google.com/mail/";
		String url = "http://img6.showhaotu.xyz/2016/09/27/8bb9a9a08bda454c7ace14f428ca6625.jpg"; // ua
		url = "https://is04.picsgonewild.com/2016/09/13/YCYTbc.jpg";// 403
	//	down(url, "d:/002/t1.jpg");
		System.out.println("--ok");
	}

	//
	// conn.setRequestProperty("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64; rv:33.0) Gecko/20100101 Firefox/33.0");

	public void down(String url, String pathname, int timeoutSec)
			throws TimeoutException

	{
//		ExecutorService es = Executors.newSingleThreadExecutor();
//		
//		
//		 
//		Future<String> fut = es.submit(new Callable<String>() {
//
//			@Override
//			public String call() throws Exception {
//				down(url, pathname);
//				return null;
//			}
//		});
		FutureTask ft=new FutureTask<>(new Callable<String>() {

			@Override
			public String call() throws Exception {
				down(url, pathname);
				return null;
			}
		});
	 	Thread thread = new Thread(ft);
		thread.setName("thread_"+url);
		thread.setPriority(Thread.MAX_PRIORITY);
	//	thread.set
		thread.start();
	 

		try {
			ft.get(timeoutSec, TimeUnit.SECONDS);
		} catch (InterruptedException e) {
			ExUtil.throwExV2(e, "--url:" + url);
			 
		} catch (ExecutionException e) {
			ExUtil.throwExV2(e, "--url:" + url);
		 
		} catch (TimeoutException e) {
		//	closeStreamAll();
			ft.cancel(true); 
			throw e;
		} finally {
			clrAll(ft);
		}

	}

	private void clrAll(FutureTask ft) {
	//	closeStreamAll();
		ft.cancel(true);
		try {
			httpClient1.getConnectionManager().shutdown();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
	
	@Deprecated
	public void down(String url, String pathname, int timeoutSec,ExecutorService exeSvs)
			throws TimeoutException

	{
	//	ExecutorService es = Executors.newSingleThreadExecutor();
		 
		Future<String> fut = exeSvs.submit(new Callable<String>() {

			@Override
			public String call() throws Exception {
				down(url, pathname);
				return null;
			}
		});

		try {
			fut.get(timeoutSec, TimeUnit.SECONDS);
		} catch (InterruptedException e) {
			ExUtil.throwExV2(e, "--url:" + url);
			 
		} catch (ExecutionException e) {
			ExUtil.throwExV2(e, "--url:" + url);
		 
		} catch (TimeoutException e) {
		//	closeStreamAll();
			throw e;
		} finally {
		//	closeStreamAll();
		}

	}

	/**
	 * attilax 2016年9月28日 上午12:50:46
	 * 
	 * @param es
	 * @param fut
	 */
	private void closeFutureTask(ExecutorService es, Future<String> fut) {

		// this.httpClient1.
	//	closeStreamAll();

		try {
			if (fut != null)
				fut.cancel(true);
		} catch (Exception e) {
			e.printStackTrace();
		}
		try {
			es.shutdown();
		} catch (Exception e) {
			e.printStackTrace();
		}
		try {

			// fut.

			es.shutdownNow();

		} catch (Exception e) {
			e.printStackTrace();
		}

		try {
			es.awaitTermination(0, TimeUnit.SECONDS);
			 
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

//	private void closeStreamAll() {
//		StreamUtil.flushNclose(this.inputStream);
//		StreamUtil.flushNclose(this.outputStream);
//	}

	public HttpClient httpClient1;
	public FileOutputStream outputStream;
	public InputStream inputStream;
	public HttpGet httpGet1;
	private void down(String url, String pathname) {

		
        
        
		filex.createAllPath(pathname);

		  httpGet1 = new HttpGet(url);
		String ua = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:33.0) Gecko/20100101 Firefox/33.0";
		// "User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64; rv:33.0) Gecko/20100101 Firefox/33.0"
		// httpGet1.setParams(new httpp);

		// 4.x版本貌似HttpClient就成了一个接口了
		// 现在都用这个来创建客户端连接,相当于打开了一个浏览器
		httpClient1 = new DefaultHttpClient();
		
		 HttpParams params=httpClient1.getParams();
		/* 超时设置 */
        /* 从连接池中取连接的超时时间 */
        ConnManagerParams.setTimeout(params, 1000);
        /* 连接超时 */
    //    HttpConnectionParams.setConnectionTimeout( 2000);
        /* 请求超时 */
    //    HttpConnectionParams.setSoTimeout( 4000);
        
   //     httpClient.getParams().setIntParameter(CoreConnectionPNames.SO_LINGER, value)  
        httpClient1.getParams().setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 60000);
        httpClient1.getParams().setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 30000);  
        
        
		httpClient1.getParams().setParameter(HttpMethodParams.USER_AGENT, ua);// 设置信息
		enableSSL(httpClient1);

		HttpResponse httpResponse1 = null;
		try {
			httpResponse1 = httpClient1.execute(httpGet1);

		} catch (Exception e) {

			ExUtil.throwExV2(e, "--url:" + url);
		}

		StatusLine statusLine = httpResponse1.getStatusLine();
		
		if (statusLine.getStatusCode() == 200) {
			// String pathname = ;
			File xml = new File(pathname);
			try {
				outputStream = new FileOutputStream(xml);
				inputStream = httpResponse1.getEntity().getContent();

				StreamUtil.streamEx(inputStream, outputStream);
			} catch (Exception e) {
				ExUtil.throwExV2(e);
			}finally{
				closeHttpConn();
				
			}

			System.out.println("存储了文件: " + xml.toString());
			
		}
		
	//	httpClient1.getConnectionManager().shutdown();
		
	//	httpResponse1.get
	//	httpGet1.getc
	 
	}

	/**
	attilax    2016年9月30日  下午3:52:25
	 */
	private void closeHttpConn() {
		try {
			httpGet1.releaseConnection();
		} catch (Exception e) {
			e.printStackTrace();
		}
	
		
		try {
			httpClient1.getConnectionManager().shutdown();
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		
	}
}
